package http

import (
	"context"
	"errors"
	"fmt"
	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	"time"
)

type Config struct {
	Endpoint  string `help:"访问地址" default:""`
	Addr      string `help:"监听IP" default:"0.0.0.0"`
	Port      uint   `help:"监听端口" default:"8989"`
	OpenPprof bool   `help:"是否打开pprof调试" releaseDefault:"false" default:"true"`
}

type Server struct {
	config *Config
	*gin.Engine
	httpSrv *http.Server
	logger  *zap.Logger
}

func NewServer(engine *gin.Engine, logger *zap.Logger, conf *Config) *Server {
	s := &Server{
		config: conf,
		Engine: engine,
		logger: logger,
	}
	return s
}

func (s *Server) Start(ctx context.Context) error {
	address := fmt.Sprintf("%s:%d", s.config.Addr, s.config.Port)
	s.httpSrv = &http.Server{
		Addr:    address,
		Handler: s,
	}
	//打开pprof
	if s.config.OpenPprof {
		pprof.Register(s.Engine, "api/debug")
	}
	if err := s.httpSrv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
		s.logger.Fatal("Http listen error", zap.String("address", address), zap.Error(err))
		return err
	}
	s.logger.Info(fmt.Sprintf("Http server start address: %s; Endpoint: %s", address, s.config.Endpoint))
	return nil
}
func (s *Server) Stop(ctx context.Context) error {
	s.logger.Info("Shutting down server...")
	// The context is used to inform the server it has 5 seconds to finish
	// the request it is currently handling
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := s.httpSrv.Shutdown(ctx); err != nil {
		s.logger.Fatal("Server forced to shutdown error", zap.Error(err))
	}
	s.logger.Info("Http server exiting")
	return nil
}
